import OssService from '@/utils/oss-uploader';
import config from './config.js';
import { Sentry } from '@/main';
var base64 = require('@/utils/base64.js');
import {
	hanleToken
} from '@/utils/utils.js';
let natIng = false;
const timeoutNum = 40000;
const whiteUrls = [
	'/repair/user-notice/unread-count',
	'/trajectory/record',
	'/blade-system/menu/routes',
	'/repair-auth/oauth/token',
	'/repair/user/weixin/official/account/info',
	'/repair/maintain/malfunction/rescue/rescueUserRunning',
	'/repair/maintain/malfunction/rescue/home/list',
	'/repair/maintain/plan/content/list',
	'/repair/maintain/plan/content/detail',
	'/blade-user/business/set',
	'/repair/maintain/elevator/detail',
	'/repair/home/user/plan/apply',
	'/tenant/config',
	'/repair/maintain/plan/content/planTypeStatistic',
	'/repair/maintain/plan/content/allow/sign',
	'/repair/user/sign/detail',
	'/repair/robot/status/', '/repair/robot/push/', '/repair/maintain/plan/content/bot/send/msg',
	'/repair/maintain/plan/content/plan/order/home/page/v3', '/repair/robot/status/', '/repair/robot/push/', '/repair/maintain/plan/content/bot/send/msg',
	'/repair/maintain/malfunction/work/user/planList/OfToday',
	'/repair-auth/login/request'];

function base64ToFile(base64String, filename) {
	const arr = base64String.split(',');
	const mime = arr[0].match(/:(.*?);/)[1];
	const bstr = atob(arr[1]);
	let n = bstr.length;
	const u8arr = new Uint8Array(n);
	while (n--) {
		u8arr[n] = bstr.charCodeAt(n);
	}
	return new File([u8arr], filename, { type: mime });
}

// 创建OssService实例，用于执行文件上传操作。
const ossService = new OssService({});
// 失败页面重定向函数
function queErr(code, url) { 
	if (natIng) {
		return;
	}
	if (url.indexOf('repair-auth/login/request') != -1) {
		return;
	}
	// return
	if (url && (whiteUrls.join(',')).indexOf(url) != -1) {
		return;
	}
	console.log('code', code, url);
	setTimeout(() => {
		natIng = false;
	}, 3000);
	natIng = true;
	let pages = getCurrentPages();
	let pag = pages[pages.length - 1].$page.fullPath;
	console.log(pag, pages.length, 'queErr');
	uni.setStorage({
		key: 'route_his',
		data: pag,
		success: () => {
			uni.redirectTo({
				url: '/pages/error/error?code=' + code,
				success: () => {
					natIng = false;
				}
			});
		}
	});
}

// 成功返回响应拦截
function responseInter(res, toast, url, requestData, method) {
	// console.log(url+'接口回调',res)

	if (res.data.code == 200) {
		return true;
	} else {
		uni.hideLoading();
		let msg = res.data.msg;
		if (res.data.code === 401) {
			msg = msg || '身份过期请重新登录';
		} else {
			if (![400].includes(res.data.code)) {
				Sentry.captureException(new Error(`【${method}】请求错误,错误码：${res.data.code}`),{
					extra: {
						// requestHeader: {
						// 	'Blade-Auth': hanleToken('get', 'token') || '',
						// 	Authorization: 'Basic ' + base64.encode('maintain:maintain')
						// },
						requestUrl: config.baseUrl + url,
						method,
						requestData: {
							...requestData
						},
						responseData:{
							...res
						}
					},
				});
			}
			if ([404].indexOf(res.data.code) != -1 || res.data.code >= 500) {
				if (toast) {
					queErr(res.data.code, url);
				}

				return;
			}
		}
		if (toast) {
			uni.showToast({
				title: msg,
				icon: 'none'
			});
		}

		return false;
	}
}

// 统一类型请求函数
function request(obj = {}) {
	let objs = Object.assign({}, obj);
	
	if (!objs.method || !objs.url) {
		uni.showToast({
			title: '请求参数错误',
			icon: 'none'
		});
		queErr(-1, objs.url);
		return;
	}
	const routePath = objs.url;
	let headerObj = {
		'content-type': 'application/x-www-form-urlencoded',
		'Blade-Auth': hanleToken('get', 'token') || '',
		Authorization: 'Basic ' + base64.encode('maintain:maintain'),
		'Role-Id': objs.roleId || false
	};
	if (objs.textPlain) {
		headerObj['content-type'] = 'text/plain';
	}
	if (objs.textJson) {
		headerObj['content-type'] = 'application/json';
	}
	if (objs.textFormData) {
		headerObj['content-type'] = 'multipart/form-data';
	}
	if (objs.textStream) {
		headerObj['content-type'] = 'application/octet-stream';
	}
	if (objs.captchaKey) {
		headerObj['Captcha-Key'] = objs.captchaKey;
	}
	if (objs.autoid) {
		headerObj.autoid = objs.autoid;
	}

	objs.header = Object.assign(headerObj, objs.header || {});
	objs.toast = true;
	objs.timeout = objs.timeout || timeoutNum;
	objs.url = config.baseUrl + objs.url;

	return new Promise((resolve, reject) => {
		if (!getApp().globalData.isConnected && objs.toast) {
			queErr(-1, routePath);
			reject({ errMsg: '无网' });
			return;
		}
		uni.request({
			...objs,
			success(res) {
				if (responseInter(res, objs.toast, routePath)) {
					resolve(res.data);
				} else {
					reject(res.data);
				}
			},
			fail(err) {
				uni.hideLoading();
				if (objs.toast) {
					queErr(-1, routePath);
				}

				reject(err);
			}
		});
	});
}

// CaptchaKey 用于验证码账号登入时添加请求头 
function post(url, data, type, toast = true, autoid = false, CaptchaKey = false, roleId = false) {
	return new Promise((resolve, reject) => {
		if (!getApp().globalData.isConnected && toast) {
			queErr(-1, url);
			reject({ errMsg: '无网' });
			return;
		}
		var headerObj = {
			'content-type': type ? 'application/json' : 'application/x-www-form-urlencoded',
			'Blade-Auth': hanleToken('get', 'token') || '',
			Authorization: 'Basic ' + base64.encode('maintain:maintain'),
			'Role-Id': roleId
		};
		if (autoid) {
			headerObj.autoid = autoid;
		}
		if (CaptchaKey) {
			headerObj['Captcha-Key'] = CaptchaKey;
		}
		if (roleId) {
			headerObj['Role-Id'] = roleId;
		}
		uni.request({
			url: config.baseUrl + url,
			method: 'POST',
			data,
			header: headerObj,
			timeout: timeoutNum,
			success(res) {
				if (responseInter(res, toast, url, data, 'POST')) {
					resolve(res.data);
				} else {
					reject(res.data);
				}
			},
			fail(err) {
				Sentry.captureException(new Error(`【POST】请求错误：【${url}】`), {
					extra: {
						requestUrl: config.baseUrl + url,
						method: 'POST',
						requestData: data,
						requestFail: err
					},
				});
				uni.hideLoading();
				if (toast) {
					queErr(-1, url);
				}

				reject(err);
			}
		});
	});
}

function get(url, data = {}, toast = true, timeout) {
	return new Promise((resolve, reject) => {
		if (!getApp().globalData.isConnected && toast) {
			queErr(-1, url);
			reject({ errMsg: '无网' });
			return;
		}
		uni.request({
			url: config.baseUrl + url,
			method: 'GET',
			data: data,
			timeout: timeout || timeoutNum,
			header: {
				'content-type': 'application/x-www-form-urlencoded',
				'Blade-Auth': hanleToken('get', 'token') || '',
				Authorization: 'Basic ' + base64.encode('maintain:maintain')
			},
			success(res) {
				if (responseInter(res, toast, url, data, 'GET')) {
					resolve(res.data);
				} else {
					reject(res.data);
				}
			},
			fail(err) {
				Sentry.captureException(new Error(`【GET】请求错误：【${url}】`), {
					extra: {
						requestUrl: config.baseUrl + url,
						method: 'GET',
						requestData: data,
						requestFail: err
					},
				});
				uni.hideLoading();
				if (toast) {
					queErr(-1, url);
				}

				reject(err);
			}
		});
	});
}
function del(url, data = {}, toast = true) {
	return new Promise((resolve, reject) => {
		if (!getApp().globalData.isConnected && toast) {
			queErr(-1, url);
			reject({ errMsg: '无网' });
			return;
		}
		uni.request({
			url: config.baseUrl + url,
			method: 'DELETE',
			data: data,
			timeout: timeoutNum,
			header: {
				'content-type': 'application/x-www-form-urlencoded',
				'Blade-Auth': hanleToken('get', 'token') || '',
				Authorization: 'Basic ' + base64.encode('maintain:maintain')
			},
			success(res) {
				if (responseInter(res, toast, url, data, 'DELETE')) {
					resolve(res.data);
				} else {
					reject(res.data);
				}
			},
			fail(err) {
				Sentry.captureException(new Error(`【DELETE】请求错误：【${url}】`), {
					extra: {
						// requestHeader: {
						// 	'Blade-Auth': hanleToken('get', 'token') || '',
						// 	Authorization: 'Basic ' + base64.encode('maintain:maintain')
						// },
						requestUrl: config.baseUrl + url,
						method: 'DELETE',
						requestData: data,
						requestFail: err
					},
				});
				uni.hideLoading();
				queErr(-1, url);
				reject(err);
			}
		});
	});
}

function put(url, data, toast = true) {
	return new Promise((resolve, reject) => {
		uni.request({
			url: config.baseUrl + url,
			method: 'PUT',
			data,
			timeout: timeoutNum,
			header: {
				// "content-type": "application/x-www-form-urlencoded",
				'Blade-Auth': hanleToken('get', 'token') || '',
				Authorization: 'Basic ' + base64.encode('maintain:maintain')
			},
			success(res) {
				if (responseInter(res, toast, url, data, 'PUT')) {
					resolve(res.data);
				} else {
					reject(res.data);
				}
			},
			fail(err) {
				Sentry.captureException(new Error(`【PUT】请求错误：【${url}】`), {
					extra: {
						// requestHeader: {
						// 	'Blade-Auth': hanleToken('get', 'token') || '',
						// 	Authorization: 'Basic ' + base64.encode('maintain:maintain')
						// },
						requestUrl: config.baseUrl + url,
						method: 'PUT',
						requestData: data,
						requestFail: err
					},
				});
				queErr(-1, url);
				reject(err);
			}
		});
	});
}
/**
 * 上传进度更新回调函数
 *
 * 该函数用于处理上传过程中的进度更新。它首先验证进度信息的有效性，然后显示一个带有当前上传进度的加载提示。
 *
 * @param {Object} res - 进度更新的信息。必须是一个对象，并且包含一个名为`progress`的数字属性，表示上传的进度。
 *                       如果`res`不是对象、为null，或者`progress`不是数字，函数将记录一个错误并返回。
 */
function onProgressUpdateCallBack(res) {
	// 验证res是否是对象、非空且包含一个名为progress的数字属性
	if (typeof res !== 'object' || res === null || typeof res.progress !== 'number') {
		// 可以替换为更合适的错误处理
		console.error('Invalid progress update:', res);
		return;
	}

	// 显示一个带有上传进度的加载提示
	uni.showLoading({
		title: `上传中... ${Math.floor(res.progress)}%`
	});
}

function uniUpload(url, imgId, options = {}) {
	console.log('upload', url, imgId, options);
	/**
	 * 使用OSS服务异步上传文件并返回上传结果。
	 *
	 * 该函数封装了一个异步操作，它创建了一个Promise对象，用于处理OSS文件上传的过程。
	 * 如果上传成功，Promise将通过resolve方法返回上传结果；如果上传失败，Promise将通过reject方法返回错误信息。
	 *
	 * @returns {Promise} 返回一个Promise对象，该对象在文件上传成功时解决为上传结果，在上传失败时拒绝为错误信息。
	 */
	return new Promise(async (resolve, reject) => {
		try {
			/**
			 * 异步方法上传文件到OSS。
			 * @param {string} tempFilePath 要上传的临时文件链接。
			 * @param {string} keyPrefix 文件在OSS中的前缀。
			 * @param {string} fileName 文件名称。
			 * @param {string} contentType 文件的Content-Type。
			 * @param {Object} meta 文件的元数据。
			 * @param {Object} callback 设置上传成功回调参数，小程序上传暂不支持。
			 * @param {Object} compress 图片压缩配置。
			 * @param {string} urlParams URL携带的参数。
			 * @param {Number} imageMaxSize 图片最大大小，默认为10M。
			 * @param {Function} onProgressUpdate 上传进度回调函数。
			 * @returns {Promise} 上传操作的Promise对象。
			 */
			const res = await ossService.uploadFile({
				tempFilePath: url,
				fileName: imgId,
				...options
			});
			// 上传成功，解决Promise并返回上传结果。 
			console.log('upload-suc',res); 
			resolve(res);
		} catch (error) {
			Sentry.captureException(new Error('【OSS】上传文件错误'), {
				extra: {
					// requestHeader: {
					// 	'Blade-Auth': hanleToken('get', 'token') || '',
					// 	Authorization: 'Basic ' + base64.encode('maintain:maintain')
					// },
					requestUrl: config.baseUrl + url,
					requestData: {
						url,
						imgId,
						options
					},
				},
			});
			uni.hideLoading();
			uni.showModal({
				title: '上传失败',
				content: JSON.stringify(error),
				showCancel: false
			});
			// uni.showToast({
			// 	title: '上传失败,请检查网络后重试',
			// 	icon: 'none'
			// })
			// 上传失败，拒绝Promise并返回错误信息。
			console.log(error, 'error');
			reject(error);
		}
	});
}

// H5 上传图片
function base64_upload(url, imgId) {
	return new Promise((resolve, reject) => {
		let base64str = url.replace(/\"/g, '');

		// 将 Base64 字符串转换为 File 实例
		const file = base64ToFile(base64str, 'file.png');

		// 创建 FormData 对象并添加文件
		const formData = new FormData();
		formData.append('file', file);
		formData.append('fileName', `${imgId}.png`);

		const controller = new AbortController();
		const signal = controller.signal;

		// 设置超时
		const timeout = setTimeout(() => {
			controller.abort();
		}, timeoutNum);

		var uploadUrl = config.baseUrl + `/blade-resource/oss/endpoint/put-file${imgId ? '-by-name' : ''}`;

		fetch(uploadUrl, {
			method: 'POST',
			body: formData,
			headers: {
				// "content-type": "application/x-www-form-urlencoded",
				'Blade-Auth': hanleToken('get', 'token') || '',
				Authorization: 'Basic ' + base64.encode('maintain:maintain')
			},
			signal: signal
		})
			.then(response => response.json())
			.then(data => {
				clearTimeout(timeout);
				if (data.code !== 200) {
					uni.hideLoading();
					uni.showToast({
						title: '上传失败,请检查网络后重试',
						icon: 'none'
					}); 
					Sentry.captureException(new Error('【base64_upload】上传失败'), {
						extra: {
							// requestHeader: {
							// 	'Blade-Auth': hanleToken('get', 'token') || '',
							// 	Authorization: 'Basic ' + base64.encode('maintain:maintain')
							// },
							requestUrl: config.baseUrl + url,
							requestData: {
								data,
								file,
								imgId
							},
						},
					});
					reject({data,imgId,url}); 
				} else {
					resolve(data);
				}
			})
			.catch(error => {
				Sentry.captureException(error, {
					extra: {
						// requestHeader: {
						// 	'Blade-Auth': hanleToken('get', 'token') || '',
						// 	Authorization: 'Basic ' + base64.encode('maintain:maintain')
						// },
						requestUrl: config.baseUrl + url,
						requestData: {
							file,
							imgId
						},
					},
				});
				clearTimeout(timeout);
				uni.showToast({
					title: '上传失败',
					icon: 'none'
				});
				reject({ error, url });
			});
	});
}

// 文件上传
function upload(url, imgId, options) {
	console.log('upload-imgId', imgId);
	console.log('upload-options', options);
	
	// check url is base64 or not
	// if (url.indexOf('data:image') !== -1) { 
	// 	return base64_upload(url, imgId,options);
	// } 
	return uniUpload(url, imgId, options);
}

function wxlogin(url) {
	return new Promise((resolve, reject) => {
		if (!getApp().globalData.isConnected) {
			queErr(-1);
			resolve(false);
			return;
		}
		uni.login({
			provider: 'weixin',
			success(res) {
				resolve(res.code);
			},
			fail(err) {
				Sentry.captureException(new Error('【wxlogin】微信登录失败'), {
					extra: {
						requestUrl: config.baseUrl + url,
					},
				});
				resolve(false);
			}
		});
	});
}

const head = async (imageUrl) => {
	let headers;
	try {
		// 通过本地代理服务器获取图片headers
		const response = await fetch(`http://localhost:8080/image-headers?url=${encodeURIComponent(imageUrl)}`);
		if (!response.ok) {
			throw new Error(`HTTP error! status: ${response.status}`);
		}
		headers = await response.json();
		console.log('Image headers:', headers);
	} catch (error) {
		console.error('Error fetching image headers:', error);
		throw error;
	}
	return headers;
};

export default {
	post,
	get,
	put,
	upload,
	wxlogin,
	del,
	head,
	uni_upload: uniUpload,
	request,
};
